package de.trebings.gia.servlets;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import de.trebings.gia.entities.Idea;
import de.trebings.gia.entities.IdeaLike;
import de.trebings.gia.entities.User;
import de.trebings.gia.util.AuthorizationException;
import de.trebings.gia.util.IdeaLikeList;
import de.trebings.gia.util.PMF;
import de.trebings.gia.util.UserManager;

@SuppressWarnings("serial")
public class IdeasServlet extends HttpServlet {

	PersistenceManager pm;
	UserManager um;
	JSONObject response;

	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		initProcessing(req);
		String action = req.getParameter("action");
		try {
			if ("authorizeViaFacebook".equals(action)) {
				String facebookAccessToken = req.getParameter("accessToken");
				authorizeViaFacebook(facebookAccessToken);
			} else if ("authorizeViaEmail".equals(action)) {
				String email = req.getParameter("email");
				String password = req.getParameter("password");
				authorizeViaEmail(email, password);
			} else if ("getIdeas".equals(action)) {
				if (isAuthorized()) {
					response.put("isAuthenticated", "X");
					getIdeas();
				} else {
					response.put("isAuthenticated", " ");
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
			throw new ServletException(e);
		}
		closeProcessing(resp);
	}

	public void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		initProcessing(req);
		String action = req.getParameter("action");
		try {
			ensureAuthorization();
			response.put("isAuthenticated", "X");
			processPost(req, action);
		} catch (JSONException e) {
			e.printStackTrace();

		} catch (AuthorizationException e) {
			try {
				response.put("isAuthenticated", " ");
			} catch (JSONException e1) {
				e1.printStackTrace();
				throw new ServletException(e);
			}
		}
		closeProcessing(resp);
	}

	private void processPost(HttpServletRequest req, String action)
			throws UnsupportedEncodingException, JSONException {
		if ("addIdea".equals(action)) {
			String title = req.getParameter("title");
			URLDecoder.decode(title, "UTF-8");
			String description = req.getParameter("description");
			URLDecoder.decode(description, "UTF-8");
			addIdea(title, description);
		} else if ("likeIdea".equals(action)) {
			long ideaId = Long.parseLong(req.getParameter("ideaId"));
			likeIdea(ideaId);
		} else if ("unLikeIdea".equals(action)) {
			long ideaId = Long.parseLong(req.getParameter("ideaId"));
			unLikeIdea(ideaId);
		}
	}

	private void ensureAuthorization() throws AuthorizationException {
		if (!isAuthorized())
			throw new AuthorizationException();
	}

	private void initProcessing(HttpServletRequest req) {
		System.out.println("Servlet: " + this.getServletName()
				+ " started (GET) from " + req.getServerName());
		pm = PMF.get().getPersistenceManager();
		um = new UserManager(pm, req.getSession());
		response = new JSONObject();
	}

	private void closeProcessing(HttpServletResponse resp) throws IOException {
		pm.close();
		String responseString = response.toString();
		System.out.println(responseString);
		resp.setContentType("application/json");
		resp.setCharacterEncoding("utf-8");
		resp.getWriter().write(responseString);
		System.out.println("Servlet: " + this.getServletName() + " ended");
	}

	private boolean isAuthorized() {
		return um.isAuthorized();
	}

	private void authorizeViaEmail(String email, String password)
			throws JSONException, IOException {
		System.out.println("auth email: " + email + ", password: " + password);

		if (um.authorizeViaEmail(email, password)) {
			response.put("isAuthenticated", "X");
			response.put("email", email);
			getIdeas();
		} else {
			response.put("isAuthenticated", " ");
		}
	}

	private void authorizeViaFacebook(String facebookAccessToken)
			throws JSONException, IOException {
		System.out.println("facebook token: " + facebookAccessToken);

		if (um.authorizeViaFacebook(facebookAccessToken)) {
			response.put("isAuthenticated", "X");
			getIdeas();
		} else {
			response.put("isAuthenticated", " ");
		}
	}

	private void likeIdea(long ideaId) throws JSONException {
		response.put("ideaId", ideaId);

		IdeaLike ideaLike = new IdeaLike(ideaId, um.getAuthorizedUser().getId());
		pm.makePersistent(ideaLike);

		response.put("likeString", getLikeList(ideaId).getLikeString(um));
		response.put("alreadyLiked", "X");
	}

	@SuppressWarnings("unchecked")
	private void unLikeIdea(long ideaId) throws JSONException {
		response.put("ideaId", ideaId);

		String queryEval = "select from " + IdeaLike.class.getName()
				+ " where ideaId == " + ideaId + " && userId == "
				+ um.getAuthorizedUser().getId();
		List<IdeaLike> ideaLikes = (List<IdeaLike>) pm.newQuery(queryEval)
				.execute();
		for (IdeaLike like : ideaLikes) {
			pm.deletePersistent(like);
		}

		response.put("likeString", getLikeList(ideaId).getLikeString(um));
		response.put("alreadyLiked", " ");
	}

	private void addIdea(String title, String description) throws JSONException {
		long userId = um.getAuthorizedUser().getId();
		System.out
				.println("Input: " + title + ":" + description + ":" + userId);
		Idea idea = new Idea(title, description, userId);
		pm.makePersistent(idea);
		getIdeas();
	}

	@SuppressWarnings("unchecked")
	private IdeaLikeList getLikeList(long ideaId) {
		String queryEval = "select from " + IdeaLike.class.getName()
				+ " where ideaId == " + ideaId;
		List<IdeaLike> ideaLikes = (List<IdeaLike>) pm.newQuery(queryEval)
				.execute();
		return new IdeaLikeList(ideaLikes);
	}

	/*
	 * gets all ideas and adds them to the response
	 */
	@SuppressWarnings("unchecked")
	private void getIdeas() throws JSONException {
		JSONArray ideaArrayJSON = new JSONArray();
		JSONObject ideaLineJSON;

		String query = "select from " + Idea.class.getName();
		List<Idea> ideas = (List<Idea>) pm.newQuery(query).execute();

		for (Idea idea : ideas) {
			//TODO remove this after migration
			//migrateDescription(idea);
			
			ideaLineJSON = new JSONObject();
			ideaLineJSON.put("id", idea.getId());
			ideaLineJSON.put("title", idea.getTitle());
			ideaLineJSON.put("description", idea.getDescription());
			ideaLineJSON.put("status", idea.getStatusDescription());

			String imageUrl = createImageUrl(idea);
			ideaLineJSON.put("imageUrl", imageUrl);

			IdeaLikeList likeList = getLikeList(idea.getId());
			ideaLineJSON.put("likeString", likeList.getLikeString(um));
			ideaLineJSON.put("alreadyLiked", likeList.getAlreadyLiked(um));

			User user = um.getUserById(idea.getUserId());
			if (user != null) {
				ideaLineJSON.put("name", user.getName());
			} else {
				ideaLineJSON.put("name", "unbekannter user");
			}
			
			ideaArrayJSON.put(ideaLineJSON);
		}

		response.put("ideas", ideaArrayJSON);
	}

	private void migrateDescription(Idea idea) {
		if("".equals(idea.getDescription())){
			idea.setDescription(idea.getDescriptionOld());
		}
	}

	private String createImageUrl(Idea idea) {
		User user = um.getUserById(idea.getUserId());
		String fbUserId = null;
		if (user != null) {
			fbUserId = user.getFbId();
		}
		
		if (fbUserId == null || "".equals(fbUserId)) {
			return "";
		} else {
			return "https://graph.facebook.com/" + fbUserId + "/picture";
		}
	}
}
